package agend.client;

import jade.core.Profile;
import jade.core.ProfileImpl;
import jade.core.Runtime;
import jade.wrapper.AgentContainer;
import jade.wrapper.AgentController;
import jade.wrapper.StaleProxyException;

import java.net.BindException;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.ServerSocket;
import java.net.SocketException;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;

import agend.client.agents.AgentClient;
import agend.client.gui.utils.HandlerView;


public class HandlerJade {

	private static Runtime runtime;

	public static void start(String username)
	{

		HandlerView.setLoginPanel();


		//avvia un istanza di jade
		runtime = Runtime.instance();

		runtime.setCloseVM(true);

		String ip="";
		String port1="";
		String port2="";

		try {
			ip=HandlerJade.getMyIp();
		} catch (SocketException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}

		port1=HandlerJade.searchPort();

		port2=searchPort();
		while(port1==port2)
			port2=searchPort();


		//creiamo un profilo per il main-container
		Profile profileMain = new ProfileImpl();

		//	profileMain.setParameter(Profile.LOCAL_HOST, "192.168.1.6");
		profileMain.setParameter(Profile.PLATFORM_ID,"ClientPlatform");
		profileMain.setParameter(Profile.LOCAL_PORT,port1);
		profileMain.setParameter(Profile.LOCAL_HOST, ip);
		profileMain.setParameter(Profile.MTPS, "jade.mtp.http.MessageTransportProtocol(http://"+ip+":"+port2+")");

		//creiamo il main-container
		AgentContainer containerMain = runtime.createMainContainer(profileMain);


		try {			
			//creiamo l'agente "danilo"
			AgentController danilo = containerMain.createNewAgent(username, AgentClient.class.getName(), new Object[0]);

			//avviamo l'agente
			danilo.start();		

		} catch (StaleProxyException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public static void shutDown()
	{
		if( runtime != null )
			runtime.shutDown();
	}


	@SuppressWarnings({ "rawtypes", "unchecked" })
	private static String getMyIp() throws SocketException{
		Enumeration ifaces = NetworkInterface.getNetworkInterfaces();

		List<NetworkInterface> listIFaces=Collections.list(ifaces);
		String ip="";

		for (NetworkInterface iface : listIFaces) {
			if(iface.isUp()){

				//System.out.println("Real iface addresses: " + iface.getDisplayName());

				String name=iface.getDisplayName();
				if(!name.contains("virtual")){

					Enumeration raddrs = iface.getInetAddresses();
					List<InetAddress> listRAddrs=Collections.list(raddrs);

					for (InetAddress raddr : listRAddrs) {
						if(!raddr.toString().contains(":") && !raddr.toString().contains("127."))
							ip=(raddr.toString().subSequence(1, raddr.toString().length())).toString();
					}
				}
			}
		}
		System.out.println(ip);
		return ip;

	}

	private static String searchPort() {

		boolean portFound = false;
		int portNumber;

		do { /* Nel ciclo do-while si cerca una porta libera */

			portNumber = (int)((49151-1024+1)*Math.random())+1024; /* Genera un numero casuale compreso fra 1024 e 49151, tale numero sar�
                           la porta su ci si metter� in ascolto */
			try {

				ServerSocket server = new ServerSocket(portNumber);

				portFound = true; /* Se la porta port � libera si pone portFound = true */
				server.close();

			} catch(BindException e) {

				if(e.getMessage().equals("Address already in use")) {
					portFound = false; /* Se viene gettata un'eccezione significa che la porta port �
                           occupata da un altro processo, in tal caso si pone portFound = false */
				}
				else {

					System.err.println("Eccezione non prevista.");
					e.printStackTrace();
				}

				try {
					Thread.sleep(50);
				} catch (InterruptedException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}

			} catch(Exception e) {

				System.err.println("Eccezione non prevista.");
				e.printStackTrace();

				try {
					Thread.sleep(50);
				} catch (InterruptedException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}

			}

		} while(!portFound);

		return String.valueOf(portNumber);
	}


	public static void main(String[] args) throws SocketException {
		
		new AgentClient();
	}
}

